#define _GNU_SOURCE
#include <unistd.h>
#include "app_bluetooth.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include "app_message.h"
#include "log/log.h"

// 缓存读取出的蓝牙数据
static char read_buf[1024];
static int read_len = 0;
static char fix_header[] = {0xF1, 0xDD};

/**
 * 等待获取蓝牙接收到ack数据（OK\r\n）
 */
static int wait_ack(Device *device)
{
    // 等待一定的时间，获取蓝牙返回的数据
    usleep(1000* 50);
    char buf[4];
    read(device->fd, buf, 4);
    if (memcmp(buf, "OK\r\n", 4) == 0)
    {
        return 0;
    }
    return -1;
}

/**
 * 测试蓝牙是否可用
 */
int app_bluetooth_status(Device *device)
{
    write(device->fd, "AT\r\n", 4);

    return wait_ack(device);
}

/**
 * 修改蓝牙名称
 */
int app_bluetooth_rename(Device *device, char *name)
{
    write(device->fd, "AT+NAME", 7);
    write(device->fd, name, strlen(name));
    write(device->fd, "\r\n", 2);

    return wait_ack(device);
}

/**
 * 设置蓝牙波特率
 */
int app_bluetooth_setBraudRate(Device *device, BTBraudRate baud_rate)
{
    write(device->fd, "AT+BAUD", 7);
    write(device->fd, baud_rate, 1);
    write(device->fd, "\r\n", 2);

    return wait_ack(device);
}

/**
 * 重启蓝牙
 */
int app_bluetooth_reset(Device *device)
{
    write(device->fd, "AT+RESET\r\n", 10);

    return wait_ack(device);
}

/**
 * 设置蓝牙网络ID
 */
int app_bluetooth_setNetID(Device *device, char *net_id)
{
    write(device->fd, "AT+NETID", 8);
    write(device->fd, net_id, strlen(net_id));
    write(device->fd, "\r\n", 2);

    return wait_ack(device);
}

/**
 * 设置蓝牙MAC地址
 */
int app_bluetooth_setMaddr(Device *device, char *maddr)  // "a3a4"
{
    write(device->fd, "AT+MADDR", 8);
    write(device->fd, maddr, strlen(maddr));
    write(device->fd, "\r\n", 2);

    return wait_ack(device);
}

/**
 * 移除缓存中指定长度的左侧数据
 */
static void move_data (int len)
{
    if (len > read_len)
    {
        len = read_len;
    }
    memmove(read_buf, read_buf+len, read_len-len);
    read_len -= len;
}

/**
 * 处理读取的蓝牙数据的函数
 data: 从蓝牙中读取的数据
 蓝牙收到的数据的三种情况：
    1. “OK\r\n”
    2. 蓝牙mesh格式数据
    3. 其它无用数据
 一次从串口读取的蓝牙数据很可能不是一个完整的数据帧，所以需要将数据帧拼接完整再处理
蓝牙mesh格式数据: f1 dd 07 23 23 ff ff 41 42 43
        f1 dd : 固定的头部
        07： 之后数据的长度（5-16之间） 
        23 23：对端（发送方）的MADDR
        ff ff: 我的MADDR或ffff(群发)
        41 42 43：发送的数据
要生成的数据：网关中message的二进制数据  conn_type id_len msg_len id msg
 */
int app_bluetooth_postRead(Device *device, char *data, int len)
{
    // 将data添加到read_buf
    memcpy(read_buf+read_len, data, len);
    read_len += len;
    // 如果read_len小于4, 说明数据不完整，直接返回
    if (read_len < 4)
    {
        return 0;
    }

    int i;
    // 遍历缓存数据
    for ( i= 0; i < read_len-3; i++)
    {
        // 如果缓存数据中存在“OK\r\n”，则说明收到了ack，将OK\r\n从缓存中移除
        if (memcmp(read_buf+i, "OK\r\n", 4) == 0)
        {
            move_data(i+4);
            return 0;
        } 
        else if (memcmp(read_buf+i, fix_header, 2) == 0) 
        {
            // 移除左侧数据
            move_data(i);
            // 如果数据长度不够，直接返回0
            if (read_len < read_buf[2] + 3)
            {
                return 0;
            }
            /*
            f1 dd 07 23 23 ff ff 41 42 43
                f1 dd : 固定的头部
                07： 之后数据的长度（5-16之间） 
                23 23：对端（发送方）的MADDR
                ff ff: 我的MADDR或ffff(群发)
                41 42 43：发送的数据
            */
            // 要生成的数据：网关中message的二进制数据  conn_type id_len msg_len id msg
            memset(data, 0, len);
            data[0] = CONN_BT; // conn_type
            data[1] = 2; // id_len
            data[2] =  read_buf[2] - 4; // msg_len
            memcpy(data+3, read_buf+3, 2); // id
            memcpy(data+5, read_buf+7, data[2]);

            // 从缓存移除这段数据
            move_data(read_buf[2] + 3);

            return data[2] + 5;
        }
    }
    // 移除i个无用数据
    move_data(i);
    
    return 0;
}

/**
 * 处理将要写入蓝牙数据函数
 data: conn_type id_len msg_len id msg
 蓝牙发送数据格式例子：
    41 54 2b 4d 45 53 48 00 ff ff 41 42 43 0d 0a
    	41 54 2b 4d 45 53 48 00： AT+MESH（固定头部）
    	ff ff: 对端的MADDR（如果是FFFF代表群发）
    	11 22 33: 要发送的数据（不超过12字节）
    	0d 0a：\r\n（固定结尾）
 */
int app_bluetooth_preWrite(Device *device, char *data, int len)
{
    // data的长度至少应该6位
    if (len < 6)
    {
        log_error("data len is too short");
        return -1;
    }

    int blue_len = 12 + data[2]; // 蓝牙发送数据长度

    char blue_data[blue_len];

    // 向blue_data写入对应格式的数据
    // AT+MESH（固定头部）
    memcpy(blue_data, "AT+MESH", 8);
    // 对端的MADDR (data中的id)
    memcpy(blue_data + 8, data +3, 2);
    // 要发送的数据（不超过12字节）  就是msg
    memcpy(blue_data + 10, data + 5, data[2]);
    // \r\n（固定结尾）
    memcpy(blue_data + 10 + data[2], "\r\n", 2);

    // 要将data中原有的数据替换为blue_data中的数据
    memset(data, 0, len);
    memcpy(data, blue_data, blue_len);

    return blue_len;
}